

#pragma once
#include <string>
#include <ctype.h>
#include <cstdint>
#include <vector>
#include <map>

enum VALUE_TYPE
{
    NUMBER  = 0x00,
    BOOLEAN = 0x01,
    STRING       = 0x02,
    START_OBJECT = 0x03,
    NULL_TYPE    = 0x05,
    ARRAY_TYPE   = 0x08,
    END_OBJECT   = 0x09

};

class AmfKey
{
public:
    AmfKey();
    int ParseAmfKey(const uint8_t * data, int length);
    int CopyBuffer(uint8_t  * data, int length);
public:
    uint16_t m_key_len;
    std::string m_key_value;
};

class AmfValue
{
public:
    AmfValue()
    {
    }
    virtual ~AmfValue()
    {
    }
    VALUE_TYPE GetValueType()
    {
        return m_type;
    }
    static AmfValue * CreateAmfValueByType(VALUE_TYPE type);
    static AmfValue * ParseBuffer(const uint8_t * data, int length, int & index);
public:
    virtual int CopyToBuffer(uint8_t * data, int length) = 0;
    virtual int ParseValueFromBuffer(const uint8_t * data, int length) = 0;
    virtual int GetLength() = 0;
protected:
    VALUE_TYPE m_type;
};

class AmfNumber : public AmfValue
{
public:
    AmfNumber();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
    double GetValue() { return m_value; }
    void SetValue(double value) { m_value = value;}
private:
    double m_value;
};

class AmfBoolean : public AmfValue
{
public:
    AmfBoolean();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
    bool GetValue() { return m_value;}
    void SetValue(bool value);
private:
    bool m_value;
};

class AmfString : public AmfValue
{
public:
    AmfString();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
    std::string GetValue() { return m_value; }
    void SetString(const std::string & value) { m_value = value;}
private:
    std::string m_value;
};

class AmfArray : public AmfValue
{
public:
    AmfArray();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
    std::string Dump();
private:
    std::vector<AmfKey>    m_key_vec;
    std::vector<AmfValue*> m_value_vec;
};

class AmfNull : public AmfValue
{
public:
    AmfNull();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
private:

};

class AmfObject : public AmfValue
{
public:
    AmfObject();
    ~AmfObject();
    int ParseValueFromBuffer(const uint8_t *data, int length) override;
    int CopyToBuffer(uint8_t *data, int length) override;
    int GetLength() override;
    std::string Dump();
    void SetNumber(const std::string & key, double number);
    void SetString(const std::string & key, const std::string & value);
    void SetBool(const std::string & key, bool value);
    void SetObject(const std::string & key, AmfObject * object);
private:
    std::map<std::string, AmfValue*> m_value_map;
};
